/*
* Copyright (c) 2008-2009, Genox Software Ltd.
* All rights reserved.
*
* Author : Toby Riley - 2009
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*     * Redistributions of source code must retain the above copyright
*       notice, this list of conditions and the following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright
*       notice, this list of conditions and the following disclaimer in the
*       documentation and/or other materials provided with the distribution.
*     * Neither the name of Genox Software Ltd. nor the
*       names of its contributors may be used to endorse or promote products
*       derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY Genox Software Ltd. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL Genox Software Ltd. BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using Microsoft.ReportingServices.Interfaces;
using Microsoft.ReportingServices.Diagnostics;
using Secure.FTPDeliveryExtension.OpenPGP;
using System.Security.Permissions;
using System.Xml;
using System.Globalization;
using System.Threading;

namespace Secure.FTPDeliveryExtension
{

[ExtensionLocalizedName(typeof(FTPStrings), "ReportServerSecureFTPDeliveryProvider"),
    StrongNameIdentityPermission(SecurityAction.LinkDemand, PublicKey =
        "00240000048000009400000006020000002400005253413100040000010001002f4d2e90a3573e" +
        "6e5c5cedc56ce60a6645172c7221e90a032cbf246f16cd28cd843fd4ddd892c4faab2dfe54d1e4" +
        "aaba2ad14c206c653d4e282da9184d8a7fa21e35f9f7d06128cc8c298e6ff6ccb2a3dc179b0518" +
        "924df992896e18cff246b01ed56602c6c609ce53b1bec20cc5d52999cd3d9aeabe056351f68fbc" +
        "20bb54c5")]
    public sealed class FTPDeliveryProvider : IDeliveryExtension, IExtension
{
    // Fields
    private string _defaultCSVTextDelimiter;
    private string _defaultCSVTextQualifier;
    private string _defaultRenderingExtension;
    private string _encryptedFileExtention;
    private string _gpgBinaryPath;
    private string _gpgHomePath;
    private bool _isPriviledgedUser;
    private IDeliveryReportServerInformation _reportServerInformation;
    private string _temporaryExportPath;

    // Methods
    public bool Deliver(Notification notification)
    {
        notification.Retry = false;
        notification.Status = "Processing...";
        try
        {
            Setting[] userData = notification.UserData;
            SubscriptionData data = new SubscriptionData();
            data.FromSettings(notification.UserData);
            DeliverToFTPServer(notification, data);
        }
        catch (Exception e)
        {
            notification.Status = "Error: " + e.Message;
            notification.Retry = true;
        }
        finally
        {
            notification.Status = "Success";
            notification.Save();
        }
        return notification.Retry;
    }

    private void DeliverToFTPServer(Notification notification, SubscriptionData settings)
    {
        string fileName = RenderReportToDisk(notification, settings);
        string filePath = Path.Combine(_temporaryExportPath, fileName);
        if (Convert.ToBoolean(settings.IsDeliveryEncrypted))
        {
            filePath = EncryptFile(filePath, settings);
            fileName = fileName + _encryptedFileExtention;
        }
        FTP ftplib = new FTP();
        try
        {
            ftplib.Connect(settings.FTPUrl, Convert.ToInt32(settings.FTPPort), settings.FTPUsername, settings.FTPPassword);
            ftplib.ChangeDir(settings.FTPFolder);
            ftplib.OpenUpload(filePath, fileName);
            while (ftplib.DoUpload() > 0L)
            {
                long num1 = (ftplib.BytesTotal * 100L) / ftplib.FileSize;
            }
            ftplib.Disconnect();
        }
        catch (Exception ex)
        {
            throw ex;
        }
        finally
        {
            ftplib = null;
        }
    }

    private string EncryptFile(string filePath, SubscriptionData settings)
    {
        GnuPG gpg = new GnuPG();
        string encryptedFilePath = filePath + _encryptedFileExtention;
        gpg.BinaryPath = _gpgBinaryPath;
        gpg.HomePath = @"C:\Program Files (x86)\GNU\GnuPG\Home";
        gpg.Recipient = settings.PGPPublicKeyUID;
        FileStream sourceFile = new FileStream(filePath, FileMode.Open);
        FileStream outputFile = new FileStream(encryptedFilePath, FileMode.Create);
        gpg.Encrypt(sourceFile, outputFile);
        sourceFile.Close();
        outputFile.Close();
        return encryptedFilePath;
    }

    private string GetFileNameFromFormat(string fileNameFormat)
    {
        DateTime dateStamp = DateTime.Now;
        return fileNameFormat.Replace("YYYY", dateStamp.Year.ToString()).Replace("MM", dateStamp.Month.ToString().PadLeft(2, '0')).Replace("DD", dateStamp.Day.ToString().PadLeft(2, '0')).Replace("HH", dateStamp.Hour.ToString("00")).Replace("NN", dateStamp.Minute.ToString("00")).Replace("SS", dateStamp.Second.ToString("00"));
    }

    private string RenderReportToDisk(Notification notification, SubscriptionData subscriptionData)
    {
        string format = _defaultRenderingExtension;
        string deviceInfo = string.Format("<DeviceInfo><FieldDelimiter>{0}</FieldDelimiter><Qualifier>{1}</Qualifier></DeviceInfo>", subscriptionData.CSVTextDelimiter, subscriptionData.CSVTextQualifier);
        string fileName = GetFileNameFromFormat(subscriptionData.FileNameFormat);
        string filePath = Path.Combine(_temporaryExportPath, fileName);
        FileStream _fileStream = null;
        RenderedOutputFile _renderedOutputFile = notification.Report.Render(format, deviceInfo)[0];
        _fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write);
        _renderedOutputFile.Data.Seek(0L, SeekOrigin.Begin);
        byte[] arr = new byte[((int) _renderedOutputFile.Data.Length) + 1];
        _renderedOutputFile.Data.Read(arr, 0, (int) _renderedOutputFile.Data.Length);
        _fileStream.Write(arr, 0, (int) _renderedOutputFile.Data.Length);
        _fileStream.Close();
        return fileName;
    }

    public void SetConfiguration(string configuration)
    {
        CultureInfo currentCulture = Thread.CurrentThread.CurrentCulture;
        try
        {
            Thread.CurrentThread.CurrentCulture = Localization.ClientPrimaryCulture;
            XmlDocument doc = new XmlDocument();
            Globals.SafeOpenXmlDocumentString(doc, configuration);
            if (doc.DocumentElement.Name == "RSSecureFTPDeliveryConfiguration")
            {
                foreach (XmlNode node in doc.DocumentElement.ChildNodes)
                {
                    string str;
                    if (((str = node.Name) != null) && (str == "TemporaryExportPath"))
                    {
                        _temporaryExportPath = node.InnerText;
                    }
                    if (((str = node.Name) != null) && (str == "EncryptedFileExtention"))
                    {
                        _encryptedFileExtention = node.InnerText;
                    }
                    if (((str = node.Name) != null) && (str == "DefaultRenderingExtension"))
                    {
                        _defaultRenderingExtension = node.InnerText;
                    }
                    if (((str = node.Name) != null) && (str == "DefaultCSVTextDelimiter"))
                    {
                        _defaultCSVTextDelimiter = node.InnerText;
                    }
                    if (((str = node.Name) != null) && (str == "DefaultCSVTextQualifier"))
                    {
                        _defaultCSVTextQualifier = node.InnerText;
                    }
                    if (((str = node.Name) != null) && (str == "GPGBinaryPath"))
                    {
                        _gpgBinaryPath = node.InnerText;
                    }
                    if (((str = node.Name) != null) && (str == "GPGHomePath"))
                    {
                        _gpgHomePath = node.InnerText;
                    }
                }
            }
        }
        catch (Exception exception)
        {
            throw new Microsoft.ReportingServices.Diagnostics.Utilities.ServerConfigurationErrorException(exception, null);
        }
        finally
        {
            Thread.CurrentThread.CurrentCulture = currentCulture;
        }
    }

    public Setting[] ValidateUserData(Setting[] settings)
    {
        SubscriptionData data = new SubscriptionData();
        return data.Validate(settings);
    }

    // Properties
    public Setting[] ExtensionSettings
    {
        get
        {
            return SubscriptionData.ExtensionSettings;
        }
    }

    public bool IsPrivilegedUser
    {
        get
        {
            return _isPriviledgedUser;
        }
        set
        {
            _isPriviledgedUser = value;
        }
    }

    public string LocalizedName
    {
        get
        {
            return "Secure FTP Delivery";
        }
    }

    public IDeliveryReportServerInformation ReportServerInformation
    {
        get
        {
            return _reportServerInformation;
        }
        set
        {
            _reportServerInformation = value;
        }
    }
}

 
 

}
